package android.tusnotas.activities;

import java.util.List;
import java.util.UUID;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.tusnotas.activities.extras.ShowInstancesActivityExtras;
import android.tusnotas.beans.AppVersion;
import android.tusnotas.beans.Instance;
import android.tusnotas.beans.PushStatus;
import android.tusnotas.connector.TusNotasCaller;
import android.tusnotas.core.GradeAnalyser;
import android.tusnotas.core.GradeAnalyserStatuses;
import android.tusnotas.core.PushSubscriptionAnalyser;
import android.tusnotas.core.VersionAnalyser;
import android.tusnotas.exception.ProcessingInstancesException;
import android.tusnotas.exception.RemoteReadingException;
import android.tusnotas.model.TusNotasModel;
import android.tusnotas.services.WebChecker;
import android.tusnotas.services.WebCheckerManager;
import android.tusnotas.util.*;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Login extends Activity{

	private Button startButton = null;
	private ProgressDialog pd = null;
	private EditText usernameEditText = null;
	private EditText passwordEditText = null;
	private TusNotasModel tusNotasModel = null;
	private Thread thread = null;
	private Thread loadingThread = null;

	private String username = null;
	private String password = null;
	private Integer frequency = null;
	private Integer notification = null;

	private AppVersion version = null;

	private final StartButtonHandler startButtonHandler = new StartButtonHandler();
	private final LoginResultHandler loginResultHandler = new LoginResultHandler();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login);
		setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        drawScreen();

        initilizeWaitingThread();
		this.loadingThread.start();
	}

	private void initilizeWaitingThread(){
		pd = ProgressDialog.show(this, 
				getResources().getString(R.string.process_dialog_title_loading),
				getResources().getString(R.string.process_dialog_message_verifying),
				Boolean.TRUE, Boolean.FALSE);
		this.loadingThread = new Thread( new Runnable() {
			@Override
			public void run() {
				try {
					manualCheckVersion();
				} catch (Exception e) {
					e.printStackTrace();
				}
				pd.dismiss();
				
			//h.sendEmptyMessage(0);
//				Message m = new Message();
//				m.what = 1;
//				h.sendMessage(m);
			}
		});
	}

	final Handler h = new Handler(){
		public void handleMessage(Message msg) {
			 switch (msg.what) {
			 // draw
			 case 1:
	            drawScreen();
	            break;
	            // version
			 case 2:
				 _wantToDownloadNewVersion(version);
	            break;
	        }
			//drawScreen();
		}           
	};


	private void drawScreen(){
		this.usernameEditText = (EditText) findViewById(R.id.usernameET);
		this.passwordEditText = (EditText) findViewById(R.id.passwordET);
//        this.usernameEditText.setText(PropertyLoader.USERNAME);
//		this.passwordEditText.setText(PropertyLoader.PASSWORD);
        Log.d("lalala00", "drawScreen");
		this.startButton = (Button) findViewById(R.id.start_button);
    }

	private void initilizeThread(){
		this.thread = new Thread( new Runnable() {
			@Override
			public void run() {
				new WebCheckerManager(Login.this).stopWebChecker();
				while (WebChecker.isRunning()){
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				doGradesLogic();
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu myMenu) {
		getMenuInflater().inflate(R.menu.menu_login, myMenu);
		return Boolean.TRUE;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.ussageinfo:
			AlertBuilder.showUsageInfo(this);
			return Boolean.TRUE;
		case R.id.about:
			AlertBuilder.showAboutInfo(this);
			return Boolean.TRUE;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private Boolean validateForm(){

		if (this.username == null || this.username.length()==0){
			AlertBuilder.showWarning(Login.this, R.string.alert_message_error_need_user);
			return Boolean.FALSE;
		}

		if (this.password == null || this.password.trim().length()==0){
			AlertBuilder.showWarning(Login.this, R.string.alert_message_error_need_pass);
			return Boolean.FALSE;
		}

		if (!NetworkManager.isNetworkAvailable(getApplicationContext())){
			AlertBuilder.showWarning(Login.this, R.string.alert_message_error_not_connection);
			return Boolean.FALSE;
		}

		return Boolean.TRUE;

	}

	// used only for login
	private void manualSubscribePush() throws RemoteReadingException, ProcessingInstancesException{
		PushSubscriptionAnalyser psa = new PushSubscriptionAnalyser();
		String appId = getApplicationContext().getPackageName();
		PushStatus status = psa.doSubscription(appId, new IdGenerator(getApplicationContext()).getId());
		// guardar como property si la suscripcion se realizo correctamente o no
		if( status.getEstado()==0){
			this.tusNotasModel.updateProperty(Properties.PUSH_SUBSCRIBED,"true");
		} else {
			this.tusNotasModel.updateProperty(Properties.PUSH_SUBSCRIBED,"false");
		}
	}

	private void manualCheckVersion() throws RemoteReadingException, ProcessingInstancesException{
		VersionAnalyser va = new VersionAnalyser();
		String appId = getApplicationContext().getPackageName();
		String clientVersion = getActualVersion();
		version = va.doGetVersion(appId, clientVersion);

		if (version!=null){
		/*Si no tengo la ultimo recurro a la nueva version*/
            if( !version.getIsLatest()){
                Message m = new Message();
                m.what = 2;
                h.sendMessage(m);
                //_wantToDownloadNewVersion(version);
            } else {
                Message m = new Message();
                m.what = 1;
                h.sendMessage(m);
            }
		} else {
			h.sendEmptyMessage(1);
		}
	}

	private void _wantToDownloadNewVersion(AppVersion version){
		String msg;
		if(version.getIsMandatory()){
			msg = getResources().getString(R.string.alert_message_new_version_mandatory);
		}else{
			msg = getResources().getString(R.string.alert_message_new_version_optional);
		}

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(msg)
		.setCancelable(true)
		.setPositiveButton(getResources().getString(R.string.button_yes), positiveDNV(version))
		.setNegativeButton(getResources().getString(R.string.button_no), negativeDNV(version));
		AlertDialog alert = builder.create();
		alert.show();

	}

	private DialogInterface.OnClickListener positiveDNV(AppVersion version){
		return (DialogInterface.OnClickListener)(new PositiveButton(version));
	}

	private class PositiveButton implements DialogInterface.OnClickListener{
		private AppVersion version;
		public PositiveButton(AppVersion version){
			this.version = version;
		}

		public void onClick(DialogInterface dialog, int id) {
			if (version.getLinkLastVersion() == null || version.getLinkLastVersion().equals("")){
				version.setLinkLastVersion("http://www.uade.edu.ar/");
			}
			callBrowser(version.getLinkLastVersion());
			if(version.getIsMandatory()){
				logout();
			}
		}
	}

	private void callBrowser(String link){
		Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
		startActivity(browserIntent);
	}

	private DialogInterface.OnClickListener negativeDNV(AppVersion version){
		if(version.getIsMandatory()){
			return (DialogInterface.OnClickListener)(new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					logout();
				}
			});
		}else{
			return (DialogInterface.OnClickListener)(new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					dialog.cancel();
				}
			});
		}
	}

	private void logout(){
		
		// delete old hash
		TusNotasModel.getTusNotasModel(getApplicationContext()).updateProperty(Properties.HASH, "");
		Log.e(getClass().getName(),"Deleted saved hash");
		
		Intent intent = new Intent("kill");
		getApplicationContext().sendBroadcast(intent);
		this.finish();
	}

	private String getActualVersion(){
		String app_ver;
		try
		{
			app_ver = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName;
		}
		catch (NameNotFoundException e)
		{
			app_ver = "not_found";
			Log.v(getClass().getSimpleName(), e.getMessage());
		}
		return app_ver;
	}

	public void loginButtonHandler(View target) {
		this.startButtonHandler.sendEmptyMessage(this.startButtonHandler.doDisable);

		try {
			this.tusNotasModel = TusNotasModel.getTusNotasModel(getApplicationContext());
			this.username = this.usernameEditText.getText().toString().trim();
			this.password = this.passwordEditText.getText().toString();
			this.frequency = Integer.parseInt(getResources().getString(R.string.default_frequency));
			this.notification = Integer.parseInt(getResources().getString(R.string.default_notif_level));

			if (!validateForm()){
				return;
			}

			this.pd = ProgressDialog.show(Login.this, 
					getResources().getString(R.string.process_dialog_title_loading), 
					getResources().getString(R.string.process_dialog_message_loading), 
					Boolean.TRUE, Boolean.FALSE);

			initilizeThread();
			this.thread.start();

		} catch (Exception e) {
			e.printStackTrace();
			AlertBuilder.showError(Login.this,R.string.alert_message_error_default);
		}
		finally{
			this.startButtonHandler.sendEmptyMessage(this.startButtonHandler.doEnable);
		}

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (this.pd!=null){
			this.pd.dismiss();
		}
	}

	private void doGradesLogic() {

		TusNotasCaller.cookie="";
		this.tusNotasModel.deleteAllGrades();
		this.tusNotasModel.deleteAllCourses();
		this.tusNotasModel.deleteAllInstances();
		this.tusNotasModel.deleteAllNews();

		this.tusNotasModel.updateProperty(Properties.USERNAME, this.username);
		this.tusNotasModel.updateProperty(Properties.PASSWORD, this.password);
		this.tusNotasModel.updateProperty(Properties.FREQUENCY, this.frequency.toString());
		this.tusNotasModel.updateProperty(Properties.NOTIF_LEVEL, this.notification.toString());
		this.tusNotasModel.updateProperty(Properties.NUM_WRONG_PASS, new Integer(0).toString());
		//Default: 10 min
		this.tusNotasModel.updateProperty(Properties.PUSH_FREQUENCY, new Integer(60*1000).toString());
		this.tusNotasModel.updateProperty(Properties.PUSH_SUBSCRIBED, "false");
		this.tusNotasModel.updateProperty(Properties.HASH,"");
		
		PropertyLoader.getInstance(getApplicationContext());

		try {
			GradeAnalyser gradeAnalyser = new GradeAnalyser();
			///////////////
			gradeAnalyser.setContext(this);
			List<Instance> instances = gradeAnalyser.doGetGrades();

			if(instances !=null ){
				gradeAnalyser.doAnaliseGrades(instances, getApplicationContext());
			}

			this.loginResultHandler.sendEmptyMessage(GradeAnalyserStatuses.NO_FAILURE);
		} catch (RemoteReadingException rwce) {
			this.loginResultHandler.sendEmptyMessage(rwce.getErrorCode());
		} catch (ProcessingInstancesException pie) {
			this.loginResultHandler.sendEmptyMessage(GradeAnalyserStatuses.PARSER_FAILURE);
		}
	}

	private class StartButtonHandler extends Handler{

		public final int doDisable = 0;
		public final int doEnable = 1;

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case doDisable:

				break;
			case doEnable:
                if (startButton != null)
				    startButton.setEnabled(Boolean.TRUE);
				break;
			}
		}
	}

	private class LoginResultHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case GradeAnalyserStatuses.NO_FAILURE:
				//TODO etapa 3: uncomment
				//  subscribe
				try {
					manualSubscribePush();
				} catch (RemoteReadingException e) {
					e.printStackTrace();
				} catch (ProcessingInstancesException e) {
					e.printStackTrace();
				}	           		
				// end comment
				Intent showInstancesIntent =  new Intent(getApplicationContext(), ShowInstancesActivity.class);
				showInstancesIntent.putExtra(ShowInstancesActivityExtras.FROM_LOGIN, Boolean.TRUE);
				startActivity(showInstancesIntent);
				finish();
				break;
			case GradeAnalyserStatuses.WRONG_USER_OR_PASS:
				AlertBuilder.showError(Login.this,R.string.alert_message_error_userpass);
				tusNotasModel.updateProperty(Properties.NUM_WRONG_PASS, new Integer(-1).toString());
				PropertyLoader.getInstance(getApplicationContext());
				break;
			case GradeAnalyserStatuses.NOT_POSSIBLE_TO_CONNECT:
				AlertBuilder.showError(Login.this,R.string.alert_message_error_network);
				break;
			case GradeAnalyserStatuses.WEIRD_FAILURE:
				AlertBuilder.showError(Login.this,R.string.alert_message_error_default);
				break;
			case GradeAnalyserStatuses.PARSER_FAILURE:
				AlertBuilder.showError(Login.this,R.string.alert_message_error_default);
				break;
			}
			if (pd != null){
				pd.dismiss();
			}
		}
	};
	
	@Override
	public void onPause()
	{
	    super.onPause();
	    Log.w("Pausing login", "");
	}

	@Override
	public void onResume()
	{
	    Log.w("Resuming login", "");
	    super.onResume();
	}

}